package br.ufal.tci.nexos.arcolive.persistence;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;

public class GenericResultSet {

	private ArrayList rows;
	private GenericMetaDataColumn[] metaData;
	private int currentRowPosition = -1;
	
	public GenericResultSet(GenericMetaDataColumn[] metaData) {
		this.rows = new ArrayList();
		this.metaData = metaData;
	}
	
	public GenericResultSet() {
		this.rows = new ArrayList();
		this.metaData = null;
	}
	
	public boolean addRow(GenericResultRow aRow) {
		if (aRow.getColumnsCount() == this.metaData.length) {
			this.rows.add(aRow);
			return true;
		} else {
			return false;
		}
	}
	
	public boolean removeRow(int index) {
		try {
			this.rows.remove(index);
			return true;
		} catch (Exception e) {
			return false;
		}		
	}
	
	public GenericResultRow getCurrentRow() {
		return (GenericResultRow) this.rows.get(this.currentRowPosition);
	}
	
	public GenericMetaDataColumn[] getMetaData() {
		return this.metaData;
	}
	
	public int size() {
		return this.rows.size();
	}
	
	public int getCurrentRowPosition() {
		return this.currentRowPosition;
	}
	
	public void toFirst() {
		this.currentRowPosition = 0;
	}
	
	public void toLast() {
		this.currentRowPosition = this.rows.size()-1;
	}
	
	public void beforeFirst() {
		this.currentRowPosition = -1;
	}
	
	public String getValue(int columnIndex) {
		return ((GenericResultRow)this.rows.get(this.currentRowPosition)).get(columnIndex);
	}
	
	public String getValue(String columnName) {
		for (int i = 0; i < this.metaData.length; i++) {
			if (this.metaData[i].getName().equals(columnName)) {
				return this.getValue(i);
			}
		}
		return "";
	}
	
	public String getStringValue(int columnIndex) {
		return this.getValue(columnIndex);
	}
	
	public String getStringValue(String columnName) {
		return this.getValue(columnName);
	}
	
	public int getIntValue(int columnIndex) {
		return Integer.parseInt(this.getValue(columnIndex));
	}
	
	public int getIntValue(String columnName) {
		return Integer.parseInt(this.getValue(columnName));
	}
	
	public Integer getIntegerValue(String columnName) {
		return new Integer(this.getValue(columnName));
	}
	
	public double getDoubleValue(int columnIndex) {
		return Double.parseDouble(this.getValue(columnIndex));
	}
	
	public double getDoubleValue(String columnName) {
		return Double.parseDouble(this.getValue(columnName));
	}
	
	public String getType(int columnIndex) {
		return (this.metaData[columnIndex].getType());
	}
	
	public String getType(String columnName) {
		for (int i = 0; i < this.metaData.length; i++) {
			if (this.metaData[i].getName().equals(columnName)) {
				return this.getType(i);
			}
		}
		return "";
	}
	
	public boolean next() {
		return this.next(false);
	}
	
	public boolean next(boolean autoRewind) {
		this.currentRowPosition++;
		if ((this.currentRowPosition) == this.rows.size()) {
			if (autoRewind) {
				this.currentRowPosition = -1;
			}
			return false;
		}
		return true;
	}
	
	
	// We have to implement numeric criteria too, this method just suport string
	// For string we have to implement "like %%" search
	public GenericResultSet searchByOneField(Hashtable columnAndValues) {
		int currentIndex = this.currentRowPosition;
		GenericResultSet result = new GenericResultSet(this.metaData);
		boolean notMatch;		
		
		this.beforeFirst();
		while (this.next()) {
			notMatch = false;
			Enumeration fields = columnAndValues.keys();
			Enumeration values = columnAndValues.elements();
			while (fields.hasMoreElements()) {
				String field = (String) fields.nextElement();
				String value = (String) values.nextElement();
				if (!this.getValue(field).equalsIgnoreCase(value)) {
					notMatch = true;
					break;
				}
			}
			
			if (!notMatch) {
				result.addRow(this.getCurrentRow());
			}
			
		}
		
		this.currentRowPosition = currentIndex;
		return result;
	}
	
	public boolean equals (Object aGenericResultSet) {
		if ((aGenericResultSet != null) && (aGenericResultSet instanceof GenericResultSet)) {
			GenericResultSet gResultSet = (GenericResultSet)aGenericResultSet;
					
			if (this.metaData.length == metaData.length) {
				for (int i = 0; i < metaData.length; i++) {
					if (!this.metaData[i].equals(metaData[i])) {
						return false;
					}
				}		
				return true;
			}
			
			return false;
		}

		return false;
	}
	
}
